<template>
    <!-- 上面搜索栏部分 -->
    <div class="search-box">
        <div class="flex">
            <div>
                <el-icon>
                    <Search />
                </el-icon>
                <span>筛选搜索</span>
            </div>
            <div>
                <el-button @click="resetForm">重置</el-button>
                <el-button @click="submitFn" type="primary">查询搜索</el-button>
            </div>
        </div>
        <div style="padding-top: 20px">
            <!-- 在input里面回车会造成刷新，大家今晚可以尝试解决一下 -->
            <!-- 在有多个搜索框的情况下添加全部清空功能 -->
            <el-form @submit.prevent="submitFn" ref="searchFormRef" :model="listParams">
                <el-form-item label="账号/姓名:" label-width="120px" prop="keyword">
                    <!-- @keyup.enter 回车事件 -->
                    <!-- <el-input v-model="listParams.keyword" placeholder="请输入账号、姓名" @keyup.enter="submitFn" /> -->
                    <el-input v-model="listParams.keyword" placeholder="请输入账号、姓名" />
                </el-form-item>
            </el-form>
        </div>
    </div>

    <!-- 添加按钮 -->
    <div class="add-box">
        <div class="left">
            <el-icon>
                <Tickets />
            </el-icon>
            <span>数据列表</span>
        </div>
        <el-button type="primary" @click="addUser">添加</el-button>
    </div>

    <!-- table表格部分 -->
    <el-table :data="tableData" style="width: 100%">
        <el-table-column prop="id" label="编号"> </el-table-column>
        <el-table-column prop="username" label="账号"></el-table-column>
        <el-table-column prop="nickName" label="姓名"></el-table-column>
        <el-table-column prop="email" label="邮箱"></el-table-column>
        <!-- 创建时间 -->
        <el-table-column prop="createTime" label="创建时间">
            <template #default="scope">
                {{ fomatDate(scope.row.createTime) }}
            </template>
        </el-table-column>

        <!-- 登陆时间 -->
        <!-- 这里有个 :formatter="自定义函数" 属性 -->
        <el-table-column prop="loginTime" label="登陆时间">
            <template #default="scope">
                {{ fomatDate(scope.row.loginTime) }}
            </template>
        </el-table-column>

        <!-- 是否启用 -->
        <el-table-column label="是否启用">
            <!-- 通过插件得到的scope是每一列里面的 数据对象 -->
            <template #default="scope">
                <el-switch v-model="scope.row.status" :active-value="1" :inactive-value="0"
                    @change="changeHandle(scope.row)">
                </el-switch>
            </template>
        </el-table-column>

        <!-- 操作 -->
        <el-table-column label="操作">
            <template #default="scope">
                <el-button link type="primary" @click="handleEdit(scope.row.id)">
                    分配角色
                </el-button>
                <el-button link type="primary" @click="editHandle(scope.row.id)">
                    编辑
                </el-button>
            </template>
        </el-table-column>
    </el-table>

    <!-- 底部分页 -->
    <ElConfigProvider :locale="zhCn">
        <el-pagination v-model:currentPage="listParams.pageNum" v-model:page-size="listParams.pageSize" background
            layout="total, sizes, prev, pager, next ,jumper" :total="total" @size-change="pageSizeChagne"
            @current-change="currentChagne" :page-sizes="[10, 20, 50, 100]" />
    </ElConfigProvider>

    <!-- 添加用户弹出对话框 -->
    <EditUser :show="showEditUser" @hide="hideClose" @refresh="getList" :data="editId" />

    <AllocRoleVue :show="showAllocRole" @hide="hideAllocRole" :data="allocRoleId" />
</template>

<script setup lang='ts'>
import EditUser from "./components/EditUser.vue"
import { reactive, toRefs, ref } from 'vue'
import { user } from "@/api"
import { fomatDate } from "@/utils"
import { ElMessage } from 'element-plus';
import { Search, Tickets } from "@element-plus/icons-vue";

import { ElConfigProvider, FormInstance } from "element-plus";
// element里面就已经帮我们准备好的 不同语言包，直接使用就行
import zhCn from "element-plus/lib/locale/lang/zh-cn";

import AllocRoleVue from "./components/AllocRole.vue";

interface IState {
    tableData: IUserModel[];
    listParams: IUserListParams;
    total: number
}
// 一般如果遇上有部分数据是复杂类型，希望它们是响应式的，一般先准备一个总的state
const state = reactive<IState>({
    tableData: [],
    listParams: {
        keyword: "",
        pageNum: 1,
        pageSize: 10,
    },
    total: 0
})

const searchFormRef = ref<FormInstance>();

// 封装请求
const getList = () => {
    // 搜索跟之前第一次请求的不同就是 搜索要带 输入框里面的数据
    user.getUserListApi(state.listParams).then((res) => {
        if (res.code === 200) {
            state.tableData = res.data.list;
            state.total = res.data.total;
        }
    });
};
// 一开始的时候需要先调用一次
getList();


// 用来搜索框方法，进行重新渲染
const submitFn = () => {
    // 搜索一定要把页码回到第一页
    state.listParams.pageNum = 1
    // 重新请求一个数组回来把数据渲染到表格里面
    getList();
};


const pageSizeChagne = (val: number) => {
    //   console.log(val);
    // 组件使用的是 v-model绑定的 listParams.pageSize 无需再次修改
    //   console.log(state.listParams);
    //   当 面容量变化的时候，需要把页面上的数据 变成对应的数量
    //   但是一定要注意一个问题，现在如果已经在最后一页，最后一页数据，只有5条，想加载更多的条数就没有了 - 提示用户 - 今晚想想怎么做
    getList();
};


const currentChagne = (val: number) => {
    // val是新的页码
    // console.log(val);
    //   获取新的数据进行渲染
    getList();
}


// 分配角色的组件是否显示
const showAllocRole = ref(false);
// 分配角色的id
const allocRoleId = ref(0);
const handleEdit = (id: number) => {
    showAllocRole.value = true;
    allocRoleId.value = id;
};

const hideAllocRole = () => {
    showAllocRole.value = false;
    allocRoleId.value = 0;
};

// 这个是当前点击的编辑的id
const editId = ref(0);

// 编辑功能的一般流程：
// 1.从服务器获取旧的数据展示在页面中
// 2.在表单里面修改完毕
// 3.把最新的数据 向服务器发请求 同步到服务器
const editHandle = (id: number) => {
    // 向服务器获取数据，是在这里获取了再传入 子组件(EditUser)
    // 还是 把id 传递给 子组件，让它自己内部实现请求 ---> 用这种
    // 这部分获取数据并渲染的代码，是完全可以被我们封闭在组件内，不会有任何的改变
    // 就需要把一个id传入 子组件(EditUser)
    editId.value = id;
    // 把编辑框显示出来
    showEditUser.value = true;
};


const changeHandle = (row: IUserModel) => {
    // console.log(id, status);

    user
        .updateUserStatusApi({
            id: row.id,
            status: row.status,
        })
        .then((res) => {
            ElMessage({
                message: res.message,
                type: res.code === 200 ? "success" : "error",
            });
            //  如果这个地方， res.code 不是200 其实也要把 switch 恢复

        }).catch((err) => {
            // 如果请求失败，会走catch
            // 把 switch 恢复成之前的状态 -

            // 方式1
            row.status = row.status === 1 ? 0 : 1;

            // 方式2
            //   let target = state.tableData.find((item) => item.id === row.id);
            //   target && (target.status = row.status === 1 ? 0 : 1);
        })

}

// 重置功能的实现：
// 1. 点击事件
// 2. 需要给el-from表单组件添加一个ref属性，得到该组件的实例
// 3. 点击的时候调用 组件实例的resetFields方法进行重置
// 4. 前提是 给 el-from 设置了 model 属性
// 5. 还需要给 el-form-item 设置相应的 prop 属性
const resetForm = () => {
    searchFormRef.value?.resetFields();
};


// 控制 EidtUser 组件是否显示的 变量
const showEditUser = ref(false);

const addUser = () => {
    // 控制 EditUser 显示
    showEditUser.value = true;
};


// 点击取消
const hideClose = () => {
    showEditUser.value = false
    // 还要把 editId 归 0
    editId.value = 0;
}


/*
    const fmtDate = (row: IUserModel) => {
    // 把row里面的 时间 修改成一个 看起来比较舒服的格式
    //   console.log(row.createTime);
    //   如果后端返回的时间是 中国的时间，直接渲染就行，
    // 但是有时候返回的不是中国的时间，需要我们自己在前端进行处理
    let date = new Date(row.createTime); // new Date的时候，js会手动帮我们转换为当前时区的时间来进行展示
    //   date 是一个中国时区的标准时间，可以自己把里面的 年月日，时分秒获取出来进行展示 - 缺点：麻烦，但是全世界通用
    // 其实还有更加简单的方法 -- 缺点：这个写法只适合固定时区
    //   date.setHours(date.getHours() + 8);
    //   return date.toJSON().replace("T", " ").slice(0, 19);

    //  这个方法也行，缺点：要手动把 / 换成 -
    return date.toLocaleString().replaceAll("/", "-");
    };

    两个时间的处理逻辑是一样的，可以做一个封装，根据不同的属性来获取时间再格式化
    const fomatDate = (row: IUserModel, key: "createTime" | "loginTime") => {
        //   如果没有时间，就返回一个空的字符串
        if (!row[key]) return "";
        let date = new Date(row[key]);
        return date.toLocaleString().replaceAll("/", "-");
    };

    const fmtDate = (row: IUserModel) => fomatDate(row, "createTime");
    const fmtDate2 = (row: IUserModel) => fomatDate(row, "loginTime"); 
*/


// state是一个响应式数据，但是我们如果在 tempatle里面使用 state里面的数据，需要 使用 state 点出来
// 一般会使用 toRefs 把里面的数据解构成多个响应式子数据
let { tableData, listParams, total } = toRefs(state)

</script>

<style lang="less" scoped>
.search-box {
    padding: 20px;
    border: 1px solid #ccc;
    border-radius: 5px;
    box-shadow: 0px 0px 6px 0px gray;
    margin-bottom: 30px;

    .flex {
        display: flex;
        justify-content: space-between;
    }

    .el-icon {
        margin-right: 10px;
    }

    .el-input {
        width: 250px;
    }
}

.add-box {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 10px;
    margin-bottom: 20px;
    border-radius: 5px;
    box-shadow: 0 0 4px 2px #ccc;

    .left {
        display: flex;
        align-items: center;
        padding: 0 10px;

        .el-icon {
            margin-right: 10px;
        }

    }

    .el-button {
        margin-right: 10px;
    }
}
</style>